package com.pet.server.ext.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

public class PreparedSql {

	public static class InsertMaker {

		public void into(String table) {
			this.table = table;
		}

		public void set(String field, Object value) {
			this.field2value.put(field, value);
		}

		public PreparedSql toPreparedSql() {
			PreparedSql pSql = new PreparedSql();
			StringBuffer fields = new StringBuffer();
			StringBuffer valueHolders = new StringBuffer();
			for (String field : field2value.keySet()) {
				pSql.values.add(field2value.get(field));
				fields.append(fields.length() == 0 ? "" : ", ").append(field);
				valueHolders.append(valueHolders.length() == 0 ? "" : ", ").append("?");
			}
			StringBuffer templateBuffer = new StringBuffer();
			templateBuffer.append("INSERT INTO `").append(table).append("`");
			templateBuffer.append(fields.toString()).append(" VALUES ");
			templateBuffer.append(valueHolders.toString());
			pSql.template = templateBuffer.toString();
			return pSql;
		}

		private LinkedHashMap<String, Object> field2value = new LinkedHashMap<String, Object>();
		private String table;
	}

	private String template;
	private List<Object> values = new ArrayList<Object>();
	
	private void setValue(PreparedStatement pStatement, Object value, int index) throws SQLException{
		if (value instanceof String) {
			pStatement.setString(index, (String)value);
		}
		else if (value instanceof Integer) {
			pStatement.setInt(index, (Integer)value);
		}
		else if (value instanceof Float) {
			pStatement.setFloat(index, (Float)value);
		}
		else if (value instanceof Double) {
			pStatement.setDouble(index, (Double)value);
		}
		else if (value instanceof Time) {
			pStatement.setTime(index, (Time)value);
		}
		else{
			pStatement.setObject(index, value);
		}
	}
	
	private void setValues(PreparedStatement pStatement) throws SQLException{
		int sqlIndex = 0;
		for (Object value : values) {
			sqlIndex ++;
			setValue(pStatement, value, sqlIndex);
		}
	}
	
	public PreparedStatement createPreparedStatement(Connection con) throws SQLException{
		PreparedStatement pStatement = con.prepareStatement(template);
		setValues(pStatement);
		return pStatement;
	}

	public PreparedStatement createPreparedStatement4Key(Connection con) throws SQLException{
		PreparedStatement pStatement = con.prepareStatement(template, Statement.RETURN_GENERATED_KEYS);
		setValues(pStatement);
		return pStatement;
	}

	public static PreparedSql format(String template, Object... params) {
		PreparedSql pSql = new PreparedSql();
		for (Object param : params) {
			pSql.values.add(param);
		}
		pSql.template = template;
		return pSql;
	}

	public static Time parseTime(String timeString) {
		try {
			long timestamp = TimeHelper.parse(timeString).getTime();
			return new Time(timestamp);
		} catch (ParseException e) {
			e.printStackTrace();
			return new Time(0);
		}
	}

}
